<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>一、直接添加属性的问题</h2>
  <script>
    // 我们从一个例子开始
    // 定义一个p标签，通过v-for指令进行遍历
    // 然后给botton标签绑定点击事件，我们预期点击按钮时，数据新增一个属性，界面也新增一行
    // <p v-for="(value,key) in item" :key="key">
    // {{ value }}
    // </p>
    // <button @click="addProperty">动态添加新属性</button>
    // 实例化一个vue实例，定义data属性和methods方法
    // const app = new Vue({
    //     el:"#app",
    //     data:()=>{
    //         item:{
    //             oldProperty:"旧属性"
    //         }
    //     },
    //     methods:{
    //         addProperty(){
    //             this.items.newProperty = "新属性"  // 为items添加新属性
    //             console.log(this.items)  // 输出带有newProperty的items
    //         }
    //     }
    // })
    // 点击按钮，发现结果不及预期，数据虽然更新了（console打印出了新属性），但页面并没有更新
  </script>

  <h2>二、原理分析</h2>
  <div>vue2是用过Object.defineProperty实现数据响应式</div>
  <h2>三、解决方案</h2>
  <div>Vue 不允许在已经创建的实例上动态添加新的响应式属性</div>
  <br>
  <div> 若想实现数据与视图同步更新，可采取下面三种解决方案：</div>
  <ul>
    <li>Vue.set()</li>
    <li>Object.assign()</li>
    <li>$forcecUpdated()</li>
  </ul>
  <h4>Vue.set()</h4>
  <div>Vue.set( target, propertyName/index, value )</div>
  <br>
  <div>参数</div>
  <ul>
    <li>{Object | Array} target</li>
    <li>{string | number} propertyName/index</li>
    <li>{any} value</li>
  </ul>
  <div>这里无非再次调用defineReactive方法，实现新增属性的响应式,关于defineReactive方法，内部还是通过Object.defineProperty实现属性拦截</div>
  <h4>Object.assign()</h4>
  <div>直接使用Object.assign()添加到对象的新属性不会触发更新,应创建一个新的对象，合并原对象和混入对象的属性</div>
  <br>
  <div>this.someObject = Object.assign({},this.someObject,{newProperty1:1,newProperty2:2 ...})</div>
  <h4>$forceUpdate</h4>
  <div>如果你发现你自己需要在 Vue中做一次强制更新，99.9% 的情况，是你在某个地方做错了事,$forceUpdate迫使Vue 实例重新渲染</div>
  <h2>小结</h2>
  <ul>
    <li>如果为对象添加少量的新属性，可以直接采用Vue.set()</li>
    <li>如果需要为新对象添加大量的新属性，则通过Object.assign()创建新对象</li>
    <li>如果你需要进行强制刷新时，可采取$forceUpdate() (不建议)</li>
  </ul>
  <div>vue3是用过proxy实现数据响应式的，直接动态添加新属性仍可以实现数据响应式</div>
</body>
</html>